package com.framework.test.core;

import com.framework.test.exceptions.AutomationException;
import com.framework.test.utils.ConfigurationManager;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.testng.ITestContext;
import org.testng.annotations.DataProvider;

import java.io.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ExcelDataProvider {

    @DataProvider(name = "excelReader")
    public static Object[][] provideData(Method method, ITestContext context) throws IOException, AutomationException {
        String className = method.getDeclaringClass().getSimpleName();
        String methodName = method.getName();
        String fileName = className.concat("-").concat(methodName);
        String testDataPath = ConfigurationManager.getProperty("testDataPath");
        
        // 尝试查找Excel文件
        ExcelFileInfo fileInfo = findExcelFile(testDataPath, fileName);
        
        if (fileInfo != null && fileInfo.inputStream != null) {
            List<Object[]> data = new ArrayList<>();

            try (Workbook workbook = createWorkbook(fileInfo.inputStream, fileInfo.isXlsx)) {
                Sheet sheet = workbook.getSheetAt(0);

                // 获取标题行
                Row headerRow = sheet.getRow(0);
                if (headerRow == null) {
                    throw new IOException("Excel file is empty or cannot be read");
                }

                int columnCount = 0;
                for (Cell cell : headerRow) {
                    columnCount++;
                }

                // 参数化文件至少有caseTitle和runFlag列
                if (columnCount < 2) {
                    throw new IOException("Excel file must have at least caseTitle and runFlag columns");
                }

                // 第一列必须为caseTitle
                String firstHeader = headerRow.getCell(0).getStringCellValue().trim();
                if (!firstHeader.equalsIgnoreCase("caseTitle")) {
                    throw new IOException("First column must be caseTitle");
                }

                // 最后一列必须为runFlag
                String lastHeader = headerRow.getCell(columnCount - 1).getStringCellValue().trim();
                if (!lastHeader.equalsIgnoreCase("runFlag")) {
                    throw new IOException("Last column must be runFlag");
                }

                // 读取数据行
                int rowCount = sheet.getPhysicalNumberOfRows();
                for (int i = 1; i < rowCount; i++) {
                    Row row = sheet.getRow(i);
                    if (row != null) {
                        // 检查runFlag是否为"Y"
                        Cell runFlagCell = row.getCell(columnCount - 1);
                        if (runFlagCell != null &&
                                runFlagCell.getCellType() == CellType.STRING &&
                                runFlagCell.getStringCellValue().trim().equalsIgnoreCase("Y")) {

                            Object[] rowData = new Object[columnCount - 1];

                            // 读取除runFlag外的所有数据
                            for (int j = 0; j < columnCount - 1; j++) {
                                Cell cell = row.getCell(j);
                                if (cell != null) {
                                    switch (cell.getCellType()) {
                                        case STRING:
                                            rowData[j] = cell.getStringCellValue().trim();
                                            break;
                                        case NUMERIC:
                                            rowData[j] = String.valueOf(cell.getNumericCellValue());
                                            break;
                                        case BOOLEAN:
                                            rowData[j] = String.valueOf(cell.getBooleanCellValue());
                                            break;
                                        default:
                                            rowData[j] = "";
                                    }
                                } else {
                                    rowData[j] = "";
                                }
                            }
                            data.add(rowData);
                        }
                    }
                }
            }

            return data.toArray(new Object[0][]);
        }
        return null;
    }
    
    /**
     * Excel文件信息内部类
     */
    private static class ExcelFileInfo {
        InputStream inputStream;
        boolean isXlsx;
        
        ExcelFileInfo(InputStream inputStream, boolean isXlsx) {
            this.inputStream = inputStream;
            this.isXlsx = isXlsx;
        }
    }
    
    /**
     * 在多个路径中查找Excel文件
     * @param testDataPath 基础测试数据路径
     * @param fileName 文件名（不含扩展名）
     * @return ExcelFileInfo 或 null
     */
    private static ExcelFileInfo findExcelFile(String testDataPath, String fileName) {
        String[] searchPaths = {
            testDataPath.concat(System.getProperty("file.separator")).concat(fileName),
            testDataPath.concat("/").concat(fileName),
            fileName,
            "testData/".concat(fileName)
        };
        
        for (String basePath : searchPaths) {
            // 优先查找xlsx格式
            InputStream xlsxStream = ExcelDataProvider.class.getClassLoader()
                .getResourceAsStream(basePath.concat(".xlsx"));
            if (xlsxStream != null) {
                return new ExcelFileInfo(xlsxStream, true);
            }
            
            // 再查找xls格式
            InputStream xlsStream = ExcelDataProvider.class.getClassLoader()
                .getResourceAsStream(basePath.concat(".xls"));
            if (xlsStream != null) {
                return new ExcelFileInfo(xlsStream, false);
            }
        }
        return null;
    }
    
    /**
     * 根据文件类型创建相应的工作簿
     * @param inputStream 输入流
     * @param isXlsx 是否为xlsx格式
     * @return Workbook
     * @throws IOException
     */
    private static Workbook createWorkbook(InputStream inputStream, boolean isXlsx) throws IOException {
        if (isXlsx) {
            return new XSSFWorkbook(inputStream);
        } else {
            return new HSSFWorkbook(inputStream);
        }
    }
}